<?php if(!defined('PUBLIC_DIR')) die('No Access!');
using('System.Data');
using('System.Data.Sql');

Cnamespace('System.Data');
class Config implements iConfig{
	private static $DBHandler;
	private static $MemoryDB;
	private static $Loading;

	public static function GetProvider(){
		if(self::$DBHandler == null && !self::$Loading)
			return self::Load();
		else
			return self::$DBHandler;
	}

	public static function IsSets($Cnamespace){
		if(self::$DBHandler == null)
			if(is_array(self::$MemoryDB)){
				if(isset(self::$MemoryDB[$Cnamespace])){
					return true;
				}else{
					return false;
				}
			}else if(!self::$Loading){
				self::Load();
			}else{
				return false;
			}
		self::$DBHandler->Query("SELECT value FROM [Config] WHERE name = '$Cnamespace' LIMIT 1;");
		$result = self::$DBHandler->FetchRow();
		return $result !== false;
	}
	public static function Get($Cnamespace){
		if(self::$DBHandler == null)
			if(is_array(self::$MemoryDB))
				if(isset(self::$MemoryDB[$Cnamespace]))
					return self::$MemoryDB[$Cnamespace];
				else
					return null;
			else if(!self::$Loading)
				self::Load();
		self::$DBHandler->Query("SELECT value FROM [Config] WHERE name = '$Cnamespace' LIMIT 1;");
		$result = self::$DBHandler->FetchRow();
		if($result === false)
			return null;
		return $result['value'];
	}
	public static function Add($Cnamespace, $Value = ""){
		if(self::$DBHandler == null)
			if(is_array(self::$MemoryDB))
				return self::$MemoryDB[$Cnamespace] = $Value;
			else if(!self::$Loading)
				self::Load();
		return self::$DBHandler->Query("INSERT INTO [Config] (name, value) VALUES ('$Cnamespace', '$Value');");
	}
	public static function Set($Cnamespace, $Value){
		if(self::$DBHandler == null)
			if(is_array(self::$MemoryDB))
				return self::$MemoryDB[$Cnamespace] = $Value;
			else if(!self::$Loading)
				self::Load();
		if(self::IsSets($Cnamespace) == false)
			return self::$DBHandler->Query("INSERT INTO [Config] (name, value) VALUES ('$Cnamespace', '$Value');");
		else
			return self::$DBHandler->Query("UPDATE [Config] SET value = '$Value' WHERE name = '$Cnamespace';");
	}
	public static function Rem($Cnamespace){
		if(self::$DBHandler == null)
			if(is_array(self::$MemoryDB)){
				unset(self::$MemoryDB[$Cnamespace]);
				return;
			}else if(!self::$Loading)
				self::Load();
		return self::$DBHandler->Query("DELETE FROM [Config] WHERE name = '$Cnamespace';");
	}

	/* Aditional functions */
	public function __isset($name){
		$name = str_replace('_', '.', $name);
		return self::IsSets($name);
	}
	public function __get($name){
		$name = str_replace('_', '.', $name);
		return self::Get($name);
	}
	public function __set($name, $value){
		$name = str_replace('_', '.', $name);
		return self::Set($name, $value);
	}
	public function __unset($name){
		$name = str_replace('_', '.', $name);
		return self::Rem($name);
	}

	private static function Load(){
		if(!self::$Loading){
			self::$Loading = true;
			if(!self::IsSets('confg.store.path') || !self::IsSets('confg.store.filename') || !self::IsSets('confg.store.type')){
				throw new Exception('Config module not configured!', E_USER_ERROR);
			}
			if (!file_exists(self::Get('confg.store.path') . self::Get('confg.store.filename')) || filesize(self::Get('confg.store.path') . self::Get('confg.store.filename')) == 0){
				Repair::Configuration();
			}
			self::$Loading = false;
			return self::$DBHandler = new \System\Data\Sql\Database(self::Get('confg.store.path') . self::Get('confg.store.filename'), self::Get('confg.store.type'));
		}
	}

	public static function Import($settings){
		if(isset($settings['confg.store.path'])){
			if(substr($settings['confg.store.path'], 0, 1) !== DS)
				$settings['confg.store.path'] = $settings['app.public.path'] . DS . $settings['confg.store.path'];
			$settings['confg.store.path'] = realpath($settings['confg.store.path']).DS;
			if(isset($settings['confg.multisites']) && $settings['confg.multisites'] === true){
				$settings['confg.store.path'] = self::FindConfigurePath($settings['confg.store.path']);
			}
			switch($settings['confg.store.type']){
				case 'SQLite3':
					if(!isset($settings['confg.store.filename']))
						$settings['confg.store.filename'] = 'Base.sqlite';
					break;
			}
		}
		self::$MemoryDB = $settings;
		self::Load();
		foreach($settings as $name => $value){
			if(strpos($name, '.path') !== false && $value != "" && substr($value, 0, 1) !== '$'){
				if(substr($value, 0, 1) !== DS)
					$value = $settings['app.public.path'] . DS . $value;
				$value = realpath($value);
				if(substr($value, -1) != (string)DS)
					$value .= DS;
			}
			self::Set($name, $value);
		}
	}
	
	private static function Repair(){
		$DBHandler = new \System\Data\Sql\Database(Config::Get('confg.store.path') . Config::Get('confg.store.filename'), Config::Get('confg.store.type'), true);
		$DBHandler->Query('CREATE TABLE [Config] (name VARCHAR(255), value VARCHAR(255));');
		//$DBHandler->Query("INSERT INTO [Config] (name, value) VALUES ('$Cnamespace', '$Value');");
		$DBHandler->Query('CREATE TABLE [Events] (name VARCHAR(255), handle VARCHAR(255));');
		//$DBHandler->Query("INSERT INTO [Events] (name, handle) VALUES ('$Name', '$Handle');");
		$DBHandler->Query('CREATE TABLE [Traces] (name VARCHAR(255), pattern VARCHAR(255), conditions VARCHAR(255), event VARCHAR(255));');
		//$DBHandler->Query("INSERT INTO [Traces] (name, pattern, conditions, event) VALUES ('article_show', '/article/:id/show', '', 'articleShow');");
		$DBHandler->Query('CREATE TABLE [Routes] (name VARCHAR(255), pattern VARCHAR(255), conditions VARCHAR(255), action VARCHAR(255), additionalParameters VARCHAR(255));');
		//$DBHandler->Query("INSERT INTO [Routes] (name, pattern, conditions, event) VALUES ('article_show', '/article/:id/show', '', 'articleShow', '');");
		$DBHandler->Close();
	}

	private static function FindConfigurePath($_confdir, $_require_settings = true, $_reset = false) {
		static $_ConfPath = '';

		if ($_ConfPath && !$_reset) {
			return $_ConfPath;
		}

		$_uri = explode(DS, $_SERVER['SCRIPT_NAME'] ? $_SERVER['SCRIPT_NAME'] : $_SERVER['SCRIPT_FILENAME']);
		$_server = explode('.', implode('.', array_reverse(explode(':', rtrim($_SERVER['HTTP_HOST'], '.')))));
		for ($k = 0; $k < 3; $k++){
			for ($i = count($_uri) - 1; $i > 0; $i--) {
				for ($j = count($_server); $j > $k; $j--) {
					$_dir = implode('.', array_slice($_server, -$j, $j-$k)) . implode('.', array_slice($_uri, 0, $i));
					$_dir = str_replace('-', '_', $_dir);
					$_dir = ucwords($_dir);
					$_dir = 'Site' . $_dir;
					if (file_exists($_confdir . $_dir . DS . 'Config.conf') &&
							(!$_require_settings || filesize($_confdir . $_dir . DS . 'Config.conf') > 0)) {
						$_ConfPath = $_confdir . $_dir . DS;
						return $_ConfPath;
					}
				}
			}
		}

		$_ConfPath = $_confdir . 'Default' . DS;
		return $_ConfPath;
	}
}